package com.hue.gulimail.gulimailorder.config;

import org.springframework.amqp.core.Message;
import org.springframework.amqp.rabbit.connection.ConnectionFactory;
import org.springframework.amqp.rabbit.connection.CorrelationData;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.amqp.support.converter.Jackson2JsonMessageConverter;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Primary;

/**
 * @Author: 姚凤桥
 * @Date: 2021/12/23 21:34
 * @Description: Rabbit配置
 * RabbitMq和Actuator的冲突解决方案：自己注入RabbitTemplate
 */
@Configuration
public class RabbitConfig {
    private RabbitTemplate rabbitTemplate;

    @Bean
    @Primary
    public RabbitTemplate rabbitTemplate(ConnectionFactory connectionFactor) {
        RabbitTemplate rabbitTemplate = new RabbitTemplate(connectionFactor);

        rabbitTemplate.setMessageConverter(jackson2JsonMessageConverter());
        this.rabbitTemplate = rabbitTemplate;
        initRabbitTemplate();

        return rabbitTemplate;
    }

    /**
     * 配置rabbit的消息转换器
     *
     * @return
     */
    @Bean
    public Jackson2JsonMessageConverter jackson2JsonMessageConverter() {
        return new Jackson2JsonMessageConverter();
    }

    /**
     * @PostConstruct: 对象创建完成后执行
     * 定制RabbitTemplate:
     * 1.设置发送端确认模式
     * 2.设置发送端失败回调模式
     * 3.设置接受端消息确认模式：
     * 默认是自动确认，只要接受端接受到消息，服务端就会移除这个消息，如果客户端处理消息时突然宕机，那么后面没有处理完的消息就会全部丢失
     * 开启了手动确认模式后只要客户端没有手动确认，即使客户端宕机了，消息还回回到队列中，不会被直接删除
     */
//    @PostConstruct
    public void initRabbitTemplate() {
        //消息发送到消息代理时的回调函数
        rabbitTemplate.setConfirmCallback(new RabbitTemplate.ConfirmCallback() {
            @Override
            public void confirm(CorrelationData correlationData, boolean b, String s) {
                //做好消息的确认机制，将发送失败的消息记录到数据库中
                System.out.println("消息发送到的Broker");
                System.out.println(correlationData);
                System.out.println(b);
                System.out.println(s);
            }
        });

        //消息发送到队列失败时的回调函数
        rabbitTemplate.setReturnCallback(new RabbitTemplate.ReturnCallback() {
            @Override
            public void returnedMessage(Message message, int i, String s, String s1, String s2) {
                System.out.println("消息发送失败:[" + new String(message.getBody()) + "]");
            }
        });
    }
}
